package com.example.demo.netty.chat;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class NettyServer {
    public static void main(String[] args) throws Exception{

        //1. 创建一个线程组：接收客户端连接
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        //2. 创建一个线程组：处理网络操作
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            //3. 创建服务器端启动对象来配置参数
            ServerBootstrap b = new ServerBootstrap();
            //4.设置两个线程组
            b.group(bossGroup,workerGroup)
                    //5.使用NioServerSocketChannel作为服务器端通道的实现（便于 Netty 做反射处理）
                    .channel(NioServerSocketChannel.class)
                    //6.设置线程队列中等待连接的个数，（当客户端连接请求速率大于 NioServerSocketChannel 接收速率的时候，会使用该队列做缓冲）
                    .option(ChannelOption.SO_BACKLOG,128)
                    //7.保持活动连接状态
                    .childOption(ChannelOption.SO_KEEPALIVE,true)
                    //8. 创建一个通道初始化对象
                    // handler()方法用于给 BossGroup 设置业务处理器
                    // childHandler()方法用于给 WorkerGroup 设置业务处理器
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel sc){
                            ChannelPipeline pipeline=sc.pipeline();
                            //9. 往Pipeline链中添加自定义的handler类
                            pipeline.addLast(new NettyServerHandler());
                        }
                    });
            System.out.println("......Server is ready......");
            //10. 绑定端口 bind方法是异步的  sync方法是同步阻塞的
            ChannelFuture cf = b.bind(6668).sync();
            System.out.println("......Server is starting......");

            //11. 关闭通道，关闭线程组
            cf.channel().closeFuture().sync(); //异步
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
            System.out.println("......关闭通道，关闭线程组......");
        }
    }
}
